import { defineStore } from 'pinia';
import { store } from '@/store';
import { PageEnum } from '@/enums/pageEnum';
import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY } from '@/enums/cacheEnum';
import { getAuthCache, setAuthCache } from '@/utils/auth';
import { useI18n } from '@/hooks/web/useI18n';
import { useMessage } from '@/hooks/web/useMessage';
import { router } from '@/router';
import { usePermissionStore } from '@/store/modules/permission';
import { RouteRecordRaw } from 'vue-router';
import { PAGE_NOT_FOUND_ROUTE } from '@/router/routes/basic';
import { isArray } from '@/utils/is';
import { h } from 'vue';
import { AppConfigEnum } from '@/enums/appEnum';
import mcApi from 'mc-c2b2m-operator-api';
import { LoginParams, LoginResModel, UserBaseInfoModel } from 'mc-c2b2m-operator-api/types/sys';

const { SysModule } = mcApi;
const { UserApi } = SysModule;

interface UserState {
  token?: string;
  roleList: string[];
  lastUpdateTime: number;
  sessionTimeout?: boolean;
  userInfo: Nullable<UserBaseInfoModel>;
}

export const useUserStore = defineStore({
  id: 'app-user',
  state: (): UserState => ({
    // user info
    userInfo: null,
    // token
    token: undefined,
    // roleList
    roleList: [],
    // Whether the login expired
    sessionTimeout: false,
    // Last fetch time
    lastUpdateTime: 0,
  }),
  getters: {
    getUserInfo(state): UserBaseInfoModel {
      return state.userInfo || getAuthCache<UserBaseInfoModel>(USER_INFO_KEY) || {};
    },
    getToken(state): string {
      return state.token || getAuthCache<string>(TOKEN_KEY);
    },
    getRoleList(state): string[] {
      return state.roleList.length > 0 ? state.roleList : getAuthCache<string[]>(ROLES_KEY);
    },
    getSessionTimeout(state): boolean {
      return !!state.sessionTimeout;
    },
    getLastUpdateTime(state): number {
      return state.lastUpdateTime;
    },
  },
  actions: {
    setToken(info: string | undefined) {
      this.token = info ? info : ''; // for null or undefined value
      setAuthCache(TOKEN_KEY, info);
    },
    setRoleList(roleList: string[]) {
      this.roleList = roleList;
      setAuthCache(ROLES_KEY, roleList);
    },
    setUserInfo(info: UserBaseInfoModel | null) {
      this.userInfo = info;
      this.lastUpdateTime = new Date().getTime();
      setAuthCache(USER_INFO_KEY, info);
    },
    setSessionTimeout(flag: boolean) {
      this.sessionTimeout = flag;
    },
    resetState() {
      this.userInfo = null;
      this.token = '';
      this.roleList = [];
      this.sessionTimeout = false;
    },
    /**
     * 登录操作
     * @param model 登录请求参数模型
     * @param appAuthMethodId 认证方式id
     */
    async login(model: LoginParams, appAuthMethodId: string): Promise<UserBaseInfoModel | null> {
      try {
        const data = await UserApi.authByAppAuthMethod(model, appAuthMethodId);
        const { authCode } = data;
        if (!authCode) return null;
        const authModel = {
          authCode,
          appKey: AppConfigEnum.APP_KEY,
          appSecret: AppConfigEnum.APP_SECRET,
        };
        const authInfo = await UserApi.authByAuthCode(authModel);
        const { accessToken } = authInfo || {};
        this.setToken(accessToken);
        return this.afterLoginAction(authInfo, true);
      } catch (error) {
        return Promise.reject(error);
      }
    },
    /**
     * 登录成功后操作
     * @param authInfo 认证信息，协助获取用户信息
     * @param goHome 是否跳转首页
     */
    async afterLoginAction(
      authInfo: LoginResModel,
      goHome?: boolean,
    ): Promise<UserBaseInfoModel | null> {
      if (!this.getToken) return null;
      // get user info
      const userInfo = await this.getUserInfoAction(authInfo);

      const sessionTimeout = this.sessionTimeout;
      if (sessionTimeout) {
        this.setSessionTimeout(false);
      } else {
        const permissionStore = usePermissionStore();
        // 动态路由加载（首次）
        if (!permissionStore.isDynamicAddedRoute) {
          const routes = await permissionStore.buildRoutesAction();
          [...routes, PAGE_NOT_FOUND_ROUTE].forEach((route) => {
            router.addRoute(route as unknown as RouteRecordRaw);
          });
          // 记录动态路由加载完成
          permissionStore.setDynamicAddedRoute(true);
        }
        goHome && (await router.replace(userInfo?.['homePath'] || PageEnum.BASE_HOME));
      }
      return userInfo;
    },
    /**
     * 获取用户信息操作
     * @param authInfo 认证信息，用户信息接口参数
     */
    async getUserInfoAction(authInfo: LoginResModel): Promise<UserBaseInfoModel | null> {
      const { userId, accessToken } = authInfo || {};
      return await this.handleUserInfo(userId, accessToken);
    },
    /**
     * 处理用户信息
     * @param userId
     * @param token
     */
    async handleUserInfo(userId?: string, token?: string) {
      if (!userId || !token) {
        token = this.getToken;
        userId = this.getUserInfo.userId || '';
      }
      if (!userId || !token) return;
      const userInfo = await UserApi.getUserBaseInfo(userId, token);
      const { orgId, functionPathList: pathList } = userInfo || {};
      // 拿不到组织id代表不是组织成员，则代表登录失败
      if (!orgId) {
        return Promise.reject({ message: '非组织成员不允许登录！' });
      }
      this.setRoleList(isArray(pathList) ? pathList : []);
      userInfo.orgId = orgId;
      userInfo.userId = userId;
      this.setUserInfo(userInfo);
      return userInfo;
    },
    /**
     * @description: logout
     */
    async logout(goLogin = false) {
      this.setToken(undefined);
      this.setSessionTimeout(false);
      this.setUserInfo(null);
      if (goLogin) {
        // 直接回登陆页
        await router.replace(PageEnum.BASE_LOGIN);
      } else {
        // 回登陆页带上当前路由地址
        await router.replace({
          path: PageEnum.BASE_LOGIN,
          query: {
            redirect: encodeURIComponent(router.currentRoute.value.fullPath),
          },
        });
      }
    },

    /**
     * @description: Confirm before logging out
     */
    confirmLoginOut() {
      const { createConfirm } = useMessage();
      const { t } = useI18n();
      createConfirm({
        iconType: 'warning',
        title: () => h('span', t('sys.app.logoutTip')),
        content: () => h('span', t('sys.app.logoutMessage')),
        onOk: async () => {
          // 主动登出，不带redirect地址
          await this.logout(true);
        },
      });
    },
  },
});

// Need to be used outside the setup
export function useUserStoreWithOut() {
  return useUserStore(store);
}
